// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <cantor/parser/ast/expr.h>
#include <cantor/parser/ast/clause.h>

namespace cantor::parser {

    /// a delegate node to help set
    /// ctor types
    struct CtorFuncExpr : DispatchExpr {
        CtorFuncExpr(pb::ast::ExprNodeType t) : DispatchExpr(t, pb::ast::expr_class_merge(pb::ast::ExprNodeClass::ENC_FUNC, pb::ast::ENC_CTOR)) {
            fn_name = nullptr;
        }

        /// Append the expression node details to a JSON object.
        nlohmann::ordered_json to_json_impl() const override;

        String fn_name;
    };

    struct CtorMapFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_map";
        CtorMapFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_MAP_CTOR_FUNC) {
                fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        MapArg arg;
    };

    struct CtorStructFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_struct";
        CtorStructFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_STRUCT_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        DictArg arg;
    };

    struct CtorUnionFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_union";
        CtorUnionFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_UNION_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        DictPair *arg = nullptr;
    };

    struct CtorArrayFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_array";
        CtorArrayFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_ARRAY_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        ExprListArg arg;
    };

    struct CtorSetFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_set";
        CtorSetFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_SET_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        ExprListArg arg;
    };

    struct CtorTupleFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_tuple";
        CtorTupleFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_TUPLE_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        ExprListArg arg;
    };

    struct CtorJsonFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_json";
        CtorJsonFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_JSON_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        DictArg arg;
    };

    struct CtorJsonArrayFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_json_array";
        CtorJsonArrayFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_JSON_ARRAY_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        ExprListArg arg;
    };

    struct CtorEnumFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_enum";
        CtorEnumFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_ENUM_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        EnumArg arg;
    };

    struct CtorProtoFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_proto";
        CtorProtoFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_PROTO_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        ProtoArg arg;
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// a construct for user-defined type
    /// syntax STRUCT ns.mytype { arg_list }
    /// the arg_list can be
    ///    * dict pair list
    ///    * map pair list
    ///    * expr list
    /// NOTICE: STRUCT is the key word, it is difference from STRUCT is that, STRUCT ctor
    ///         no "ns.mytype" following
    ///
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    struct CtorUdfFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_udf";
        CtorUdfFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_UDF_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;
        UdfArg arg;
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// we never using CtorDefaultFuncExpr, but place here to notice
    /// that all the type should have constructor
    /// but some type, eg int/int8/string is well
    /// known by system and is primitive, so we reduce
    /// a function node leave it for system to do it self,
    /// for the type hint the constructor type
    ///
    /// for performance, primitive type construction is
    /// most frequently, using less node will cost much less
    /// memory and cpu.
    ///
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    struct CtorDefaultFuncExpr final: CtorFuncExpr {
        static constexpr const char * func_name = "construct_default";
        CtorDefaultFuncExpr() : CtorFuncExpr(pb::ast::ExprNodeType::ENT_DEFAULT_CTOR_FUNC) {
            fn_name = func_name;
        }

        nlohmann::ordered_json to_json() const override;

        DispatchExpr *arg = nullptr;
    };
}  // namespace cantor::parser
